package com.koomii.myproject.service.impl;


import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.koomii.myproject.service.IdSequenceService;
import com.koomii.myproject.tx.IdSequenceTx;

/**
 *
 * IdSequenceServiceImpl
 *
 * @author 
 *
 */
@Service("idSequenceService")
public class IdSequenceServiceImpl  implements IdSequenceService{
	
	public static final Integer firstValue = 1;//所有Id的初始值
	
	private static Map<String, IdStep> idSequenceMap = new HashMap<String, IdSequenceServiceImpl.IdStep>();
	
	
	@Autowired
	private IdSequenceTx idSequenceTx;
	
	public synchronized Integer getId(String idKey,Integer stepValue){
		//获取idStep
		IdStep idStep = getIdStep(idKey,stepValue);
		return idStep.getNextValue();
	}
	
	private synchronized IdStep getIdStep(String idKey,Integer stepValue){
		IdStep idStep = idSequenceMap.get(idKey);
		if(idStep != null){//存在则返回
			return idStep;
		}
		//不存在则从数据库查询
		Integer idParentValue = idSequenceTx.getAndUpdateNextIdSequence(idKey, firstValue);
		idStep = new IdStep(idKey,idParentValue,stepValue);
		idSequenceMap.put(idKey, idStep);
		return idStep;
	}
	
	/**
	 * id增长器
	 */
	class IdStep{
		private String idKey;
		private Integer nextValue;
		private Integer maxValue;
		private Integer stepValue = 100;//步长100，每次个种子可以生成100个主键;
		
		/**
		 * 初始化
		 * @param parentValue 种子
		 */
		public IdStep(String idKey,Integer parentValue,Integer stepValue){
			this.idKey = idKey;
			if(stepValue != null){
				this.stepValue = stepValue;
			}
			genValue(parentValue);
		}
		
		/**
		 * 根据种子Id生成nextValue和MaxValue
		 */
		private void genValue(Integer parentValue){
			this.nextValue = parentValue * this.stepValue;
			this.maxValue = this.nextValue + this.stepValue - 1;
		}

		public synchronized Integer getNextValue(){
			Integer returnValue = nextValue;
			this.nextValue += 1;
			//用尽生成器则启用一下个码段
			if(nextValue > maxValue){
				Integer parentValue = idSequenceTx.getAndUpdateNextIdSequence(idKey, returnValue);
				genValue(parentValue);
			}
			return returnValue;
		}
	}
	
}